import random

import pygame

# 定义屏幕大小
SCREEN_RECT = pygame.Rect(0, 0, 500, 1000)
# 定义刷新帧率
FRAME_PER_SEC = 100
# 定义敌机定时器事件（常量）
CREATE_ENEMY_EVENT = pygame.USEREVENT
# 定义发射子弹定时器事件（常量）
FIRE_BULLET_EVENT = pygame.USEREVENT + 1

class GameSprite(pygame.sprite.Sprite):
    """ 飞机大战——游戏精灵类 """

    def __init__(self, image_name, speed=1):
        # 调用父类的初始化方法
        super().__init__()
        # 定义属性（加载图像、获取rect、设置速度）
        self.image = pygame.image.load(image_name)
        self.rect = self.image.get_rect()
        self.speed = speed

    def update(self):
        # 移动：向上或下移动（传递负值时向下方向移动）
        self.rect.y += self.speed


class BackgroundSprite(GameSprite):
    """ 背景精灵 """
    def __init__(self, is_alternate=False):
        # 1.调用父类方法，初始化背景图
        super().__init__("./images/background03.png")
        # 2.判断是否需要交替图像，如果需要，将初始位置设置到屏幕的上方
        if is_alternate:
            self.rect.y = self.rect.height

    def update(self):
        # 1.调用父类的方法实现
        super().update()
        # 2.判断是否移除屏幕，如果移除屏幕则放到最上方
        if self.rect.y >= self.rect.height:
            self.rect.y = - self.rect.height


class EnemySprite(GameSprite):
    """ 敌机精灵 """
    def __init__(self):
        # 1.调用父类方法，设置敌机图片
        super().__init__("./images/enemy.png")
        # 2.设置敌机随机速度
        self.speed = random.randint(1, 3)
        # 3.设置敌机随机位置
        self.rect.x = random.randint(0, SCREEN_RECT.width - self.rect.width)

    def update(self):
        # 1.调用父类方法，保持垂直方向的飞行
        super().update()
        # 2.判断是否飞出屏幕(敌机底部 >= 屏幕底部，即屏幕高度)
        if self.rect.bottom >= SCREEN_RECT.height:
            # 3.如果飞出屏幕，需要从精灵组删除，调用kill方法
            self.kill()


class Hero(GameSprite):
    """ 英雄飞机 """
    def __init__(self):
        # 1.调用父类初始化方法设置图片和速度
        super().__init__("./images/hero02.png", 0)
        # 2.设置英雄的初始位置（屏幕中间，距底部长度为120）
        self.rect.centerx = SCREEN_RECT.centerx
        self.rect.bottom = SCREEN_RECT.bottom - 120
        self.is_vertical = False
        self.is_horizontal = False
        self.bullets = pygame.sprite.Group()

    def update(self):
        # 英雄飞机水平移动
        if self.is_horizontal:
            self.rect.x += self.speed
        # 英雄飞机的垂直移动
        if self.is_vertical:
            self.rect.y += self.speed
        # 控制英雄的移动边界：英雄飞机不能飞出屏幕外
        if self.rect.x < 0:
            self.rect.x = 0
        if self.rect.right > SCREEN_RECT.right:
            self.rect.right = SCREEN_RECT.right
        if self.rect.y < 0:
            self.rect.y = 0
        if self.rect.bottom > SCREEN_RECT.bottom:
            self.rect.bottom = SCREEN_RECT.bottom

    def fire(self):
        """ 发射子弹 """
        # 一次发射3个子弹
        for i in (0, 1, 2):
            # 1.创建子弹
            bullet = Bullet()
            # 2.设置子弹初始位置(与飞机中心对齐且在飞机前端)
            bullet.rect.centerx = self.rect.centerx
            bullet.rect.bottom = self.rect.top - i * 30
            # 3.将子弹精灵添加到精灵组
            self.bullets.add(bullet)


class Bullet(GameSprite):
    """ 子弹精灵 """
    def __init__(self):
        # 1.调用父类方法，设置子弹图片，设置初始速度
        super().__init__("./images/bullet.png", -2)

    def update(self):
        # 1.调用父类方法，让子弹沿垂直方向飞行
        super().update()
        # 2.判断子弹是否飞出屏幕，如果飞出屏幕，则从精灵组删除
        if self.rect.bottom < 0:
            self.kill()
